package com.qfmy.core.aop;

import com.qfmy.common.utils.JwtUtils;
import com.qfmy.core.base.service.TokenService;
import com.qfmy.core.constant.CommonConstants;
import com.qfmy.core.pojo.entity.ErrorCode;
import com.qfmy.core.pojo.entity.ResultMessage;
import com.qfmy.core.pojo.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @ClassName: InterfaceAspect
 * @author： zhengjt
 * @data： 2022/5/27 15:12
 * @version：1.0
 * @描述： 接口切面类；用来统一处理返回信息
 */
@Slf4j
@Aspect
@Component
public class InterfaceAspect {

    @Autowired
    private TokenService tokenService;

    /**
     * 切所有@ResponseBody注解的类
     */
    //@Pointcut("@annotation(org.springframework.web.bind.annotation.ResponseBody)")
    public void responseBodyAspect() {
    }

    /**
     * 切 controller
     */
    @Pointcut("execution(* com.qfmy.project.controller..*(..)) || execution(* com.qfmy.project.*.controller..*(..))")
    public void controllerAspect() {
    }

    /**
     * 前置切面
     *
     * @param point
     */
//    @Before(value = "controllerAspect()")
    public void before(JoinPoint point) {
        log.info("======== 进入前置切面 ========");
    }

    /**
     * 后置切面
     *
     * @param point
     */
//    @After(value = "responseBodyAspect()")
    public void after(JoinPoint point) {
        log.info("切 ResponseBody注解的类");
        log.info("======== 进入后置切面 ========");
    }

    /**
     * 环切
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("controllerAspect()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        log.info(" ====== 进入 around 切面 ====== ");
        //  获取请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //  获取token，登录拦截已对token进行校验，此处无需在此进行校验
        String token = request.getHeader(CommonConstants.AUTH_TOKEN);

        //  获取请求方式
        String method = request.getMethod();
        log.info("请求方式 ： {}", method);
        if (!CommonConstants.METHOD_GET.equals(method)) {
            //  Get请求代表仅查询数据，无需更新token, 非GET请求带表增删改，需要更新token
            token = tokenService.refreshToken(token);
        }

        //  返回信息处理
        try {
            Object proceed = point.proceed();


            //  如果控制层返回返回对象，则无需另外处理，直接返回
            if (proceed instanceof ResultMessage) {
                return proceed;
            }
            //  成功后的返回信息 ；
            ResultMessage resultMessage = new ResultMessage(true, 200, token, "", proceed);
            return resultMessage;
        } catch (CustomException customException) {
            log.error(" ===== 自定义异常，返回信息错误 ===== ");
            ErrorCode errorCode = customException.getErrorCode();
            if (Objects.nonNull(errorCode)) {
                Integer code = errorCode.getCode();
                String message = customException.getMessage() != null ? customException.getMessage() : errorCode.getMessage();
                log.error("自定义异常信息 ： " + message);
//                return new ResultMessage(false,code,message);
                return new ResultMessage(false, code, token, message, null);
            } else {
                log.error(" ===== 异常消息为空 ===== ");
                errorCode = ErrorCode.ERROR_UNKNOWN;
                Integer code = errorCode.getCode();
                String message = errorCode.getMessage();
//                return new ResultMessage(false,code,message);
                return new ResultMessage(false, code, token, message, null);
            }

        } catch (Exception e) {
            log.error("系统发生未知异常 ： " + e);
            ErrorCode errorCode = ErrorCode.ERROR_UNKNOWN;
            Integer code = errorCode.getCode();
            String message = errorCode.getMessage();
//            return new ResultMessage(false,code,message);
            return new ResultMessage(false, code, token, message, null);
        }

    }

}
